package ru.spb.osll.myfit.server.parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import ru.spb.osll.myfit.common.Include;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableCell;
import ru.spb.osll.myfit.common.TableStyle;
import ru.spb.osll.myfit.common.WikiText;
import ru.spb.osll.myfit.server.Converter;
import ru.spb.osll.myfit.util.CollectionUtils;
import ru.spb.osll.myfit.util.StringUtils;

public class PageParser {
  private Logger LOG = Logger.getLogger(PageParser.class);
  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
  public static final String TABLE_SEPARATOR = LINE_SEPARATOR + LINE_SEPARATOR;
  public static final String IMPORT_TABLE = "Import";


  Converter m_converter;
  public PageParser (Converter converter){
    m_converter = converter;
  }
  
  public List<PageElement> parsePage(Collection<String> lines) {
       return parsePage(new ArrayList<String>(lines));
 }
  
  public List<PageElement> parsePage(List<String> lines){
    ArrayList<PageElement> elements = new ArrayList<PageElement>();
    TableStyle style = TableStyle.UNKNOWN_FIXTURE;
    boolean flagTable = false;

    List<String> tableLines = new LinkedList<String>();
    String textLines = "";
    Pattern pattern = Pattern.compile("!include\\s*(.*)");
    for (String line : lines) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.matches()) {
          String path = matcher.group(1).trim();        
          LOG.debug("PageParser: IncludeLine: " + line);
        
          Include include = new Include();
          include.setPath(path);
          elements.add(include);
          
      } else if (line.matches("\\|.*\\|")) {
        LOG.debug("PageParser: TableLine: " + line);
        tableLines.addAll(CollectionUtils.filter(CollectionUtils.list(line.split("\\|")), StringUtils.FILTER_NOT_EMPTY));
        tableLines.add(LINE_SEPARATOR);
        flagTable = true;
      } else {
        if (flagTable == true) {
          LOG.debug("PageParser: CreateTable: " + line);
          Table table = createTable(style, tableLines);
          if (table.getData().size() != 0) {
            if (!table.getData().get(0).get(0).getText().equals(IMPORT_TABLE)) {
              elements.add(table);
            }
          }
          tableLines = new LinkedList<String>();
          flagTable = false;
        }

        LOG.debug("PageParser: MayBeText: " + line);
        if (line.length() > 0 && !line.equals(LINE_SEPARATOR)) {
          if (!(line.length() > 5 && line.substring(0, 5).equals("!path"))) {
            LOG.debug("PageParser: TextLine: " + line);
            textLines += line + LINE_SEPARATOR;
            LOG.debug("PageParser: textLines.length: " + textLines.length());
          }
        } else {
        	String lineWiki = textLines.trim();
        	
          if (lineWiki.length() > 0) {
           
            elements.add(createWikitext(lineWiki));
          }
          textLines = "";
        }
      }
    }

    if (tableLines.size() > 0) {
      Table table = createTable(style, tableLines);
      if (table.getData().size() != 0) {
        if (!table.getData().get(0).get(0).getText().equals(IMPORT_TABLE)) {
          elements.add(table);
        }
      }
    }

	String lineWiki = textLines.trim();
    if (lineWiki.length() > 0) {   
      elements.add(createWikitext(lineWiki));
    }
  
    return elements;
  }

  public WikiText createWikitext(String wiki){
    String htmlText = m_converter.convertWikiToHtml(wiki);
    WikiText wikiText = new WikiText(wiki, htmlText);
    return wikiText;
  }
  
  public Table parseTable(Collection<String> lines) {
    return createTable(TableStyle.UNKNOWN_FIXTURE, tokenizeLines(lines));
  }
  
  public Table createTable(TableStyle style, String... lines) {
    return createTable(style, CollectionUtils.list(lines));
  }
  
  public Table createTable(TableStyle style, Collection<String> lines) {
    Table table = new Table(style);

    Vector<TableCell> tableLine = new Vector<TableCell>();
    for (String line : lines) {
      if (!line.equals(LINE_SEPARATOR) && !line.isEmpty()) {
        tableLine.add(new TableCell(line));
      } else if (tableLine.size() > 0) {
        table.addLine(tableLine);
        tableLine = new Vector<TableCell>();
      }
    }

    if (tableLine.size() > 0) {
      table.addLine(tableLine);
    }

    return table;
  }
  
  private List<String> tokenizeLines(Collection<String> lines) {
    LinkedList<String> splitLines = new LinkedList<String>();
    for (String line : lines) {
      if (line.matches("\\|.*\\|")) {
        splitLines
            .addAll(CollectionUtils.filter(CollectionUtils
                .list(line.split("\\|")),
                StringUtils.FILTER_NOT_EMPTY));
        splitLines.add(LINE_SEPARATOR);
      } else {
        splitLines.add(TABLE_SEPARATOR);
      }
    }

    return splitLines;
  }
}
